package com.iking.toolkit.util.ofd.utils;

import com.iking.toolkit.model.Msg;
import com.iking.toolkit.util.PdfUtil;
import com.iking.toolkit.util.ofd.OFDRender;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.ofdrw.converter.ConvertHelper;
import org.ofdrw.converter.GeneralConvertException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.mock.web.MockMultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;

/**
 * pdf转ofd
 *
 * @author gblfy
 * @date 2021-12-06
 */
@Slf4j
public class OfdPdfUtil {
    private static final Logger logger = LoggerFactory.getLogger(OfdPdfUtil.class);

    /**
     * 将MultipartFile（PDF）转换为OFD格式的MultipartFile
     *
     * @param pdfFile 上传的PDF文件
     * @return 转换后的OFD文件（MultipartFile）
     */
    public static Msg<MultipartFile> pdfToOfd(MultipartFile pdfFile) {
        try {
            pdfFile = PdfUtil.toImagePdf(pdfFile, 144);
        } catch (IOException e) {
            return Msg.fail("pdf文件转换图片类pdf失败");
        }
        // 基础校验
        if (pdfFile.isEmpty()) {
            return Msg.fail("上传的PDF文件为空，请重新上传");
        }

        String originalFilename = pdfFile.getOriginalFilename();
        if (originalFilename == null || !originalFilename.toLowerCase().endsWith(".pdf")) {
            return Msg.fail("请上传扩展名为.pdf的文件");
        }

        // 临时文件处理
        File tempInputFile = null;
        File tempOutputFile = null;
        try {
            // 1. 创建自定义临时PDF文件
            tempInputFile = File.createTempFile("custom-pdf-", ".pdf");
            Files.write(tempInputFile.toPath(), pdfFile.getBytes());
            tempInputFile.deleteOnExit();

            // 2. 创建临时输出OFD文件
            tempOutputFile = File.createTempFile("custom-ofd-", ".ofd");
            tempOutputFile.deleteOnExit();

            // 3. 执行PDF转OFD转换
            OFDRender.convertPdfToOfd(
                    Files.newInputStream(tempInputFile.toPath()),
                    Files.newOutputStream(tempOutputFile.toPath())
            );

            // 4. 验证转换结果
            if (tempOutputFile.length() == 0) {
                return Msg.fail("OFD文件生成失败，内容为空");
            }

            // 5. 将临时OFD文件转换为MultipartFile
            byte[] ofdBytes = Files.readAllBytes(tempOutputFile.toPath());
            String ofdFileName = originalFilename.replace(".pdf", ".ofd");

            MultipartFile resultFile = new MockMultipartFile(
                    "file",
                    ofdFileName,
                    "application/ofd",  // OFD的MIME类型
                    ofdBytes
            );

            log.info("PDF转OFD成功，原文件名：{}，转换后大小：{} bytes",
                    originalFilename, resultFile.getSize());
            return Msg.sucess(resultFile);

        } catch (Exception e) {
            String errorMsg = "PDF转OFD失败：" + e.getMessage();
            log.error(errorMsg, e);
            return Msg.fail(errorMsg);
        } finally {
            // 清理临时文件
            if (tempInputFile != null && tempInputFile.exists() && !tempInputFile.delete()) {
                log.warn("临时PDF文件清理失败：{}", tempInputFile.getAbsolutePath());
            }
            if (tempOutputFile != null && tempOutputFile.exists() && !tempOutputFile.delete()) {
                log.warn("临时OFD文件清理失败：{}", tempOutputFile.getAbsolutePath());
            }
        }
    }

    /**
     * 将 OFD 格式的 MultipartFile 转换为 PDF 格式的 MultipartFile
     *
     * @param ofdFile 上传的 OFD 文件
     * @return 转换后的 PDF 文件（MultipartFile）
     */
    public static Msg<MultipartFile> ofdToPdf(MultipartFile ofdFile) {
        if (ofdFile.isEmpty()) {
            return Msg.fail("上传的OFD文件为空，请重新上传");
        }

        String originalFilename = ofdFile.getOriginalFilename();
        if (originalFilename == null || !originalFilename.toLowerCase().endsWith(".ofd")) {
            return Msg.fail("请上传扩展名为.ofd的文件");
        }

        // 关键：提前将文件内容读入字节数组，脱离Tomcat临时文件
        byte[] ofdBytes;
        try {
            ofdBytes = ofdFile.getBytes(); // 同步阶段读取文件内容到内存
        } catch (IOException e) {
            log.error("读取OFD文件内容失败", e);
            return Msg.fail("读取文件失败：" + e.getMessage());
        }

        // 临时文件处理
        File tempOfdFile = null;
        File tempPdfFile = null;
        try {
            // 1. 创建自定义临时OFD文件（使用字节数组写入，不依赖Tomcat临时文件）
            tempOfdFile = File.createTempFile("custom-ofd-", ".ofd");
            Files.write(tempOfdFile.toPath(), ofdBytes); // 将内存中的字节写入临时文件
            tempOfdFile.deleteOnExit();

            // 2. 创建临时PDF文件
            tempPdfFile = File.createTempFile("custom-pdf-", ".pdf");
            tempPdfFile.deleteOnExit();

            // 3. 执行转换
            Path srcPath = tempOfdFile.toPath();
            Path dstPath = tempPdfFile.toPath();
            ConvertHelper.toPdf(srcPath, dstPath);

            // 4. 验证转换结果
            if (tempPdfFile.length() == 0) {
                return Msg.fail("PDF生成失败，内容为空");
            }

            // 5. 转换为MultipartFile
            byte[] pdfBytes = Files.readAllBytes(dstPath);
            String pdfFileName = originalFilename.replace(".ofd", ".pdf");

            MultipartFile resultFile = new MockMultipartFile(
                    "file", pdfFileName, "application/pdf", pdfBytes
            );

            log.info("OFD转PDF成功，原文件名：{}", originalFilename);
            return Msg.sucess(resultFile);

        } catch (GeneralConvertException e) {
            log.error("转换逻辑异常", e);
            return Msg.fail("转换失败：" + e.getMessage());
        } catch (Exception e) {
            log.error("处理异常", e);
            return Msg.fail("处理失败：" + e.getMessage());
        } finally {
            // 清理临时文件
            if (tempOfdFile != null && !tempOfdFile.delete()) {
                log.warn("临时OFD文件清理失败：{}", tempOfdFile);
            }
            if (tempPdfFile != null && !tempPdfFile.delete()) {
                log.warn("临时PDF文件清理失败：{}", tempPdfFile);
            }
        }
    }

    /**
     * pdf转ofd
     *
     * @param pdfFileInputPath
     * @param ofdFileOutputPath
     */
    public static void convertToOfdByStream(String pdfFileInputPath, String ofdFileOutputPath) {
        Path input = Paths.get(pdfFileInputPath);
        Path output = Paths.get(ofdFileOutputPath);
        for (int i = 0; i < 1; i++) {
            try {
                OFDRender.convertPdfToOfd(Files.newInputStream(input), Files.newOutputStream(output));
            } catch (Exception e) {
                logger.error("test convert failed", e);
            }
        }
    }

    /**
     * pdf转ofd
     *
     * @param pdfFileInputPath
     * @param ofdFileOutputPath
     */
    public static void convertToOfd(String pdfFileInputPath, String ofdFileOutputPath) {
        Path input = Paths.get(pdfFileInputPath);
        Path output = Paths.get(ofdFileOutputPath);
        for (int i = 0; i < 1; i++) {
            try {
                byte[] pdfBytes = FileUtils.readFileToByteArray(input.toFile());
                byte[] ofdBytes = OFDRender.convertPdfToOfd(pdfBytes);
                if (Objects.nonNull(ofdBytes)) {
                    FileUtils.writeByteArrayToFile(output.toFile(), ofdBytes);
                    logger.info("pdf convert to ofd done, pdf file save to {}", output.toAbsolutePath().toString());
                } else {
                    logger.error("pdf convert to ofd failed");
                }
            } catch (Exception e) {
                logger.error("test convert failed", e);
            }
        }
    }

    /**
     * ofd转pdf
     *
     * <p>
     * 转换文档你需要:
     * 1.提供待转换OFD文档，支持Path、InputStream。
     * 2.提供转换后PDF文档位置。
     * 3.调用转换工具执行文档转换。
     *
     * @param ofdFileOutputPath
     * @param pdfFileInputPath
     */
    public static void ofdToPdf(String ofdFileOutputPath, String pdfFileInputPath) {
        // 1. 文件输入路径
        Path src = Paths.get(ofdFileOutputPath);
        // 2. 转换后文件输出位置
        Path dst = Paths.get(pdfFileInputPath);
        try {
            // 3. OFD转换PDF
            ConvertHelper.toPdf(src, dst);
            System.out.println("生成文档位置: " + dst.toAbsolutePath());
        } catch (GeneralConvertException e) {
            // GeneralConvertException 类型错误表明转换过程中发生异常
            e.printStackTrace();
        }
    }


}
